package com.danbay.cloud.device.service;

import com.danbay.cloud.base.constants.Const;
import com.danbay.cloud.base.constants.DeviceType;
import com.danbay.cloud.device.api.dto.DeviceInfoDto;
import com.danbay.cloud.device.api.dto.DeviceLoginDto;
import com.danbay.cloud.device.api.service.IDeviceLoginService;
import com.danbay.cloud.device.client.DeviceAccessClient;
import com.danbay.cloud.device.entity.CenterControl;
import com.danbay.cloud.device.entity.DeviceCollector;
import com.danbay.cloud.device.entity.DeviceInfo;
import com.danbay.cloud.device.entity.EnergyDevice;
import com.danbay.cloud.device.mapper.CenterControlMapper;
import com.danbay.cloud.device.mapper.DeviceCollectorMapper;
import com.danbay.cloud.device.mapper.DeviceInfoMapper;
import com.danbay.cloud.device.mapper.EnergyDeviceMapper;
import com.danbay.framework.exception.BusinessException;
import com.danbay.framework.utils.BeanValidator;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 *
 * @author SJG
 * 2017/10/23
 */
@Slf4j
@Service
public class DeviceLoginService implements IDeviceLoginService {

    private final CenterControlMapper centerControlMapper;

    private final EnergyDeviceMapper energyDeviceMapper;

    private final DeviceCacheService deviceCacheService;

    private final DeviceInfoMapper deviceInfoMapper;

    private final DeviceCollectorMapper deviceCollectorMapper;

    private final DeviceAccessClient deviceAccessClient;

    private final DeviceOfflineService deviceOfflineService;

    @Autowired
    public DeviceLoginService(CenterControlMapper centerControlMapper, EnergyDeviceMapper energyDeviceMapper, DeviceCacheService deviceCacheService,DeviceInfoMapper deviceInfoMapper,DeviceCollectorMapper deviceCollectorMapper,DeviceAccessClient deviceAccessClient,
                              DeviceOfflineService deviceOfflineService) {
        this.centerControlMapper = centerControlMapper;
        this.energyDeviceMapper = energyDeviceMapper;
        this.deviceCacheService = deviceCacheService;
        this.deviceInfoMapper = deviceInfoMapper;
        this.deviceCollectorMapper = deviceCollectorMapper;
        this.deviceAccessClient = deviceAccessClient;
        this.deviceOfflineService = deviceOfflineService;
    }

    /**
     * 设备登录，每次入网后都需要登录
     * @param loginDto
     * @throws BusinessException
     */
    @Override
    public void login(DeviceLoginDto loginDto) throws BusinessException {
        BeanValidator.valid(loginDto);
        //更新登录信息
        updateDeviceLoginInfo(loginDto,true);
    }

    /**
     * 设备登出，中控检测到设备连不上后，需要向云端发起设备登出
     * @param loginDto
     * @throws BusinessException
     */
    @Override
    public void logout(DeviceLoginDto loginDto) throws BusinessException {
        BeanValidator.valid(loginDto);
        //更新登录信息
        updateDeviceLoginInfo(loginDto,false);
        //缓存状态变为离线
        deviceCacheService.setDeviceOffline(loginDto.getDevId());
        //添加日志信息记录
        log.warn("设备:{}离线",loginDto.getDevId());
    }

    /**
     * 更新设备登录信息
     * 设备登出,这里缓存一条登出数据,48小时失效:这里的做法是缓存一条数据,后面直接进行查询.
     * @param loginDto
     * @param isLogin
     * @throws BusinessException
     */
    private void updateDeviceLoginInfo(DeviceLoginDto loginDto, boolean isLogin) throws BusinessException {
        String loginStatus=isLogin?Const.BOOL_STRING_FALSE:Const.BOOL_STRING_TRUE;
        //取缓存的设备信息
        DeviceInfoDto deviceInfoDto= deviceCacheService.getDeviceInfo(loginDto.getDevId());
        //中控
        if(deviceInfoDto.getDeviceType()== DeviceType.CENTRAL_CONTROL.value()){
            CenterControl centerControl = centerControlMapper.selectOne(CenterControl.builder().deviceId(loginDto.getDevId()).build());
            if(centerControl==null){
                throw new BusinessException("该中控:"+loginDto.getDevId()+"数据不存在");
            }
            if(Const.BOOL_STRING_TRUE.equals(centerControl.getHasDelete())){
                throw new BusinessException("该中控:"+loginDto.getDevId()+"已删除,不能登录或登出");
            }
            //ip
            centerControl.setRemoteAddr(loginDto.getIp());
            //在线状态
            centerControl.setStatus(loginStatus);
            centerControl.setDeviceTime(DateTime.now().toDate());
            centerControl.setVersion(loginDto.getVersion());
            //更新设备登录信息
            centerControlMapper.updateById(centerControl);
            //更新缓存
            updateDeviceCache(loginDto);
            //缓存中控离线消息
            deviceOfflineService.cacheCenterControlState(centerControl,isLogin);
            return;
        }
        if (deviceInfoDto.getDeviceType() == DeviceType.EM_METER.value()
                    || deviceInfoDto.getDeviceType() == DeviceType.WATER_METER.value()) {
            //设备是无线水电表 EnergyDevice表存无线水电表
            EnergyDevice energyDevice = energyDeviceMapper.selectOne(EnergyDevice.builder().deviceId(loginDto.getDevId()).build());
            if(energyDevice==null){
                throw new BusinessException("该设备:"+loginDto.getDevId()+"数据不存在");
            }
            //if(Const.BOOL_STRING_TRUE.equals(energyDevice.getHasDelete())){
            //    throw new BusinessException("该水电表:"+loginDto.getDevId()+"已删除,不能登录或登出");
            //}
            //ip
            energyDevice.setUserAddress(loginDto.getIp());
            //在线状态
            energyDevice.setStatus(loginStatus);
            //更新设备登录信息
            energyDeviceMapper.updateById(energyDevice);
            //缓存水电表离线消息
            deviceOfflineService.cacheMeterState(energyDevice,isLogin,deviceInfoDto.getDeviceType());
            //更新缓存
            updateDeviceCache(loginDto);
            return;
        }
        if (deviceInfoDto.getDeviceType() == DeviceType.LOCK_IN.value()
                    || deviceInfoDto.getDeviceType() == DeviceType.LOCK_OUT.value()){
            //门锁,DeviceInfo表存的是门锁
            DeviceInfo deviceInfo = deviceInfoMapper.selectOne(DeviceInfo.builder().deviceId(loginDto.getDevId()).build());
            if(deviceInfo != null)
            {
                //if(Const.BOOL_STRING_TRUE.equals(deviceInfo.getHasDelete())){
                //    throw new BusinessException("该门锁:"+loginDto.getDevId()+"已删除,不能登录或登出");
                //}
                //ip
                deviceInfo.setRemoteAddr(loginDto.getIp());
                //在线状态
                deviceInfo.setStatus(loginStatus);
                deviceInfo.setDeviceTime(DateTime.now().toDate());
                deviceInfo.setDeviceModelVer(loginDto.getVersion());
                //更新设备登录信息
                deviceInfoMapper.updateById(deviceInfo);
                //缓存门锁离线消息
                deviceOfflineService.cacheLockState(deviceInfo,isLogin);
                //更新缓存
                updateDeviceCache(loginDto);
                return;
            }
        }
        if (deviceInfoDto.getDeviceType() == DeviceType.PA.value()){
            //PA
            if (isLogin) {
                updateDeviceCache(loginDto);
            }
        }
        if (deviceInfoDto.getDeviceType() == DeviceType.COLLECTOR.value()){
            //水电表采集器
            DeviceCollector deviceCollector = deviceCollectorMapper.selectOne(DeviceCollector.builder()
                                                .deviceId(deviceInfoDto.getDevId()).build());
            if (null != deviceCollector){
                //if(Const.BOOL_STRING_TRUE.equals(deviceCollector.getHasDelete())){
                //    throw new BusinessException("该门锁:"+loginDto.getDevId()+"已删除,不能登录或登出");
                //}
                //ip
                deviceCollector.setAddress(loginDto.getIp());
                //在线状态
                deviceCollector.setStatus(loginStatus);
                deviceCollector.setVersion(loginDto.getVersion());
                //更新设备登录信息
                deviceCollectorMapper.updateById(deviceCollector);
                //更新缓存
                updateDeviceCache(loginDto);
                //获取采集器的下接档案数
                if (isLogin){
                    deviceAccessClient.getCount(deviceCollector.getDeviceId());
                }else {
                    offLineCollector(deviceCollector.getDeviceId());
                }
                return;
            }
        }
    }

    private void offLineCollector(String deviceId) {
        //下线采集器下接设备
    }

    /**
     * 更新设备缓存
     * @param loginDto 登录信息
     */
    private void updateDeviceCache(DeviceLoginDto loginDto){
        //缓存
        DeviceInfoDto deviceInfo=new DeviceInfoDto();
        deviceInfo.setDevId(loginDto.getDevId());
        deviceInfo.setIp(loginDto.getIp());
        deviceCacheService.updateRegDeviceInfo(deviceInfo);
        //设置为在线；
        setDeviceOnline(loginDto);
    }

    /**
     * 设置设备在线
     * @param loginDto 设备信息
     */
    private void setDeviceOnline(DeviceLoginDto loginDto) {
        //设备离线时设置为上线
        if(!deviceCacheService.isDeviceOnline(loginDto.getDevId()))
        {
            deviceCacheService.setDeviceOnline(loginDto.getDevId(),loginDto.getIp());
            log.info("设备:{}上线,IP:{}",loginDto.getDevId(),loginDto.getIp());
        }
    }
}
